<?php
/**
 * DolphinGTK - phpGtk framework
 *
 * @package    DolphinGTK
 * @author     Askarov Ruslan
 * @copyright  Askarov Ruslan (c) 2010.
 * @link       http://groups.google.com/group/dolphingtk
 * @license    http://www.opensource.org/licenses/gpl-license.php GPL
 * @version    0.1
 * @since      PHP v.: 5.2.1
 * @subpackage desktop
 * @category   library
 * @filesource
 */

final class Tray
{
  private static $_tray;
  private static $_created_notify = false;
  private static $_tooltip_window;
  private static $menu = null;
  private static $notifys = false;
  private static $_activate_id = 0;



  /**
   * Метод по умолчанию. Разрешаем использование
   * методов, только как статические.
   *
   * @access public
   * @return void
   */
  public function __construct()
  {
    throw new Exception(
      'Class "Tray" used only static methods. And cannot be constructed!'
    );
  }



  /**
   * Метод для проверки наличия метода
   *
   * @access private
   * @param  string $foo
   * @return bool
   */
  private static function ext( $foo = '' )
  {
    if( !self::$_tray ) {
      Log::fatal('GtkStatusIcon not initialized!');
    }
    elseif( $foo && method_exists(self::$_tray, $foo) ) {
      return true;
    }
    else {
      Log::error('Method "%s" not exists in GtkStatusIcon class!', $foo);
      return false;
    }
  }




  /**
   * Метод для создания трея
   *
   * @access public
   * @return void
   */
  public static function create()
  {
    if( class_exists('GtkStatusIcon') ) {
      self::$_tray = new GtkStatusIcon;
    } else {
      Log::fatal('GtkStatusIcon class not exists!');
    }
  }




  /**
   * Метод для указания видимости
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function visible( $flag = true )
  {
    if( self::ext( 'set_visible' ) ):
    if( $flag === true ) {
      self::$_tray->set_visible($flag);
    } else {
      self::$_tray->set_visible(false);
    }
    endif;
  }




  /**
   * Метод для указания мигания иконки в трее
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function blinking( $flag = true )
  {
    if( self::ext( 'set_blinking' ) ):
    if( $flag === true ) {
      self::$_tray->set_blinking(true);
    } else {
      self::$_tray->set_blinking(false);
    }
    endif;
  }



  /**
   * Метод для задания подсказки
   *
   * @access public
   * @param  string $tips
   * @return void
   */
  public static function tooltips( $tips = '' )
  {
    if( self::ext( 'set_tooltip' ) && !empty($tips) )
    {
      self::$_tray->set_tooltip($tips);
    }
  }




  /**
   * Метод для создания иконки
   *
   * @access public
   * @param  string $img
   * @return void
   */
  public static function icon( $img = '' )
  {
    if( self::ext( 'set_from_file' ) ):
    if( $img && file_exists(BASE_DIR.$img) ) {
      self::$_tray->set_from_file(
        BASE_DIR.$img
      );
    }
    endif;
  }




  /**
   * Метод для создания меню и привязки к трею
   *
   * @access public
   * @param array $menu
   * @param bool  $activate
   * @return void
   */
  public static function menu( $menu, $activate = false )
  {
    if( is_array($menu) && is_bool($activate) )
    {
      if( self::$menu === null )
      {
        self::$menu = $menu;
        self::$_tray->connect(
          'popup-menu', array('Tray', 'on_tray_popup_menu')
        );
      }
      else
      {
        Log::error('Tray menu defined!');
      }

      self::activate( $activate );
    }
    else
    {
      Log::fatal('Tray menu is not array or activate not is bool!');
    }
  }




  /**
   * Метод для показать/скрыть главное окно программы.
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function activate( $flag )
  {
    if( $flag === true )
    {
      self::$_activate_id = self::$_tray->connect(
        'activate', array('Tray', 'hide_or_show')
      );
    }
    elseif( $flag === false && self::$_activate_id )
    {
      if( self::$_tray->is_connected(self::$_activate_id) )
      {
        self::$_tray->disconnect(self::$_activate_id);
      }
      else
      {
        Log::msg('Not connected!');
      }
    }
  }




  /**
   * Метод для показать/скрыть главное окно программы.
   *
   * @access public
   * @param  bool $flag
   * @return void
   */
  public static function block( $flag )
  {
    if( self::ext( 'block' ) ):
    if( self::$_activate_id && self::$_tray->is_connected(self::$_activate_id) )
    {
      if( $flag === true )
      {
        self::$_tray->block(self::$_activate_id);
      }
      elseif( $flag === false )
      {
        self::$_tray->unblock(self::$_activate_id);
      }
    }
    else
    {
      Log::msg('Not connected!');
    }
    endif;
  }




  public static function on_tray_popup_menu()
  {
    if( class_exists('Menu') )
    {
      $menu = Menu::create(self::$menu);
      if( $menu ) {
        $menu->show_all();
        $menu->popup();
      } else {
        Log::fatal('Tray menu not created!');
      }
    }
    else {
      Log::fatal('Menu library not loaded!');
    }
  }




  /**
   * Метод для показа/сокрытия главного окна
   *
   * @access public
   * @return void
   */
  public static function hide_or_show()
  {
    if( Win::$_window->is_visible() ) {
      Win::$_window->hide_all();
    } else {
      Win::$_window->show_all();
    }
  }




  /**
   * Метод для вывода окошка с сообщением в трее.
   *
   * @access public
   * @param  string $msg
   * @param  int    $time
   * @param  string $bg
   * @return bool
   */
  public static function notify( $msg, $time = 3000, $bg = '#F7FFAF' )
  {
    if( self::$_created_notify ) return false;
    self::$_created_notify = true;

    if( empty($msg) ) return false;

    $icon_file = BASE_DIR . Win::$icon;
    
    if( file_exists( $icon_file ) )
    {
      $icon_file = $icon_file;
    }
    else
    {
      $icon_file = null;
    }

    if( Win::$os == 'linux' )
    {
      $ubuntu = OS::exec('uname -a | grep Ubuntu');
      $nsend  = OS::exec('which notify-send');

      if( !empty($ubuntu[0]) && !empty($nsend[0]) )
      {
        if( file_exists($nsend[0]) )
        {
          if( is_array($msg) )
          {
            if( $icon_file ) {
              $image = " -i $icon_file";
            }
            $msg[0] = '"'.escapeshellcmd($msg[0]).'"';
            $msg[1] = '"'.escapeshellcmd($msg[1]).'"';
            OS::exec("notify-send {$msg[0]} {$msg[1]} $image");
          }
          else
          {
            $msg = escapeshellcmd($msg);
            OS::exec("notify-send '$msg'");
          }
          
          self::$notifys = true;
          return true;
        }
      }
    }


    self::$_tooltip_window = new GtkWindow(Gtk::WINDOW_POPUP);

    self::$_tooltip_window->set_size_request(
      300, 175
    );


    $top  = Win::$screen_height;
    $left = Win::$screen_width - 300;
    self::$_tooltip_window->move($left, $top);

    for( $i = 0; $i < 11; $i ++ ) {
      $top  = $top - 15;
      Gtk::timeout_add((50*$i), array('Tray','move_notify'), $left, $top);
    }

    Gtk::timeout_add($time, array('Tray','from_top_notify'));

    self::$_tooltip_window->set_name('gtk-tooltips');
    self::$_tooltip_window->set_resizable(false);
    self::$_tooltip_window->set_border_width(4);
    self::$_tooltip_window->set_app_paintable(True);
    self::$_tooltip_window->modify_bg(
    Gtk::STATE_NORMAL,
    GdkColor::parse($bg)
    );

    $frame = new GtkFrame();
    $hbox = new GtkHBox();
    $frame->set_size_request(300, 175);
    $frame->show();
    $hbox->show();

    self::$_tooltip_window->add($frame);

    if( $icon_file ) {
      $icons = GtkImage::new_from_file($icon_file);
      $icons->set_alignment(0.1, 0.1);
      $icons->show();
      $hbox->pack_start($icons,0,0);
    }

    if( is_array($msg) )
    {
      $title = new GtkLabel('');
      $title->set_line_wrap(true);
      $title->set_use_markup(true);
      $title->set_text($msg[0]);
      $title->modify_font(new PangoFontDescription("Times New Roman Bold 10"));
      $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse('#366B7F'));
      $title->set_size_request(250, 15);

      $messg = new GtkLabel('');
      $messg->set_line_wrap(true);
      $messg->set_use_markup(true);
      $messg->set_text($msg[1]);
      $messg->set_size_request(230, 120);
      $messg->set_alignment(0, 0);

      $vbox = new GtkVBox();
      $vbox->pack_start($title, true, 1);
      $vbox->pack_start($messg, true, false);

      $title->show();
      $messg->show();
      $vbox->show();
      
      $hbox->pack_start($vbox);
    }
    else
    {
      $label = new GtkLabel('');
      $label->set_line_wrap(true);
      $label->set_use_markup(true);
      $label->set_text($msg);
      $label->set_alignment(0.1, 0.1);
      $label->show();
      
      $hbox->pack_start($label,0,0);
    }

    self::$_tooltip_window->child->add($hbox);
    self::$_tooltip_window->show();


    $size = self::$_tooltip_window->size_request();

    return true;
  }




  /**
   * Метод для сдвига сообщения
   *
   * @access public
   * @param  int $left
   * @param  int $top
   * @return void
   */
  public static function move_notify($left, $top)
  {
    self::$_tooltip_window->move($left, $top);
  }




  /**
   * Метод для сдвига сообщения
   *
   * @access public
   * @return void
   */
  public static function from_top_notify()
  {
    if( self::$notifys == false && self::$_created_notify === true ) {

      $top  = Win::$screen_height - 175;
      $left = Win::$screen_width - 300;
      
      for( $i = 0; $i < 11; $i ++ ) {
        $top  = $top + 15;
        Gtk::timeout_add((50*$i), array('Tray','move_notify'), $left, $top);
      }
      
      Gtk::timeout_add((50*($i+1)), array('Tray','hide_notify'), $left, $top);
    }
  }




  /**
   * Метод для сокрытия сообщения
   *
   * @access public
   * @return void
   */
  static function hide_notify()
  {
    if( self::$_created_notify === true ):
    self::$_created_notify = false;
    self::$_tooltip_window->hide();
    self::$_tooltip_window->destroy();
    endif;
  }

}
?>